﻿Imports Lucene.Net.Index
Imports Lucene.Net.Search
Imports Lucene.Net.Documents

Imports Aricie.DNN.Services
Imports Aricie.DNN.Modules.LuceneSearch.Business
Imports Aricie.DNN.Modules.LuceneSearch.Logs
Imports DotNetNuke.Common.Utilities
Imports System.Globalization

Namespace Aricie.DNN.Modules.LuceneSearch.UI

    Partial Public Class PeriodFilter
        Inherits LuceneFilterControlBase

#Region "Private Attributes"
        Private _fieldName As String = DnnSearchItemField.PubDate

        Private Const glbFilterTypeSingle As String = "DateFilter - Single Date"
        Private Const glbFilterTypeRange As String = "DateFilter - Date Range"
#End Region

#Region "Public Properties"
        Public Property FieldName() As String
            Get
                Return _fieldName
            End Get
            Set(ByVal value As String)
                _fieldName = value
            End Set
        End Property

        Private _useLucenDateFormat As Boolean = True
        Public Property UseLucenDateFormat() As Boolean
            Get
                Return _useLucenDateFormat
            End Get
            Set(ByVal value As Boolean)
                _useLucenDateFormat = value
            End Set
        End Property


        Public Overrides Property Enabled() As Boolean
            Get
                Return Me.rbPeriod.Enabled
            End Get
            Set(ByVal value As Boolean)
                Me.rbPeriod.Enabled = value
                Me.decStartDate.Enabled = value
                Me.decEndDate.Enabled = value
                Me.rbDate.Enabled = value
                Me.decSpecificDate.Enabled = value
            End Set
        End Property

#End Region

        Public Sub New()
            ' par défaut, on est en mode filtre
            QueryMode = UI.QueryMode.Filter
        End Sub

#Region "ILuceneFilterControl implements"

        Public Overrides Function GetFilter() As LuceneFilterQuery
            Dim toReturn As New LuceneFilterQuery
            Dim dateStart As Date
            Dim dateEnd As Date

            If rbPeriod.Checked Then
                Dim periodFilters As TermRangeQuery = Nothing

                If decStartDate.Value IsNot Nothing AndAlso decEndDate.Value IsNot Nothing Then
                    dateStart = ConvertToDateTime(decStartDate.Value)
                    dateEnd = ConvertToDateTime(decEndDate.Value)
                    periodFilters = GetPeriodFilter(dateStart, dateEnd)

                ElseIf decStartDate.Value IsNot Nothing AndAlso decEndDate.Value Is Nothing Then
                    dateStart = ConvertToDateTime(decStartDate.Value)
                    dateEnd = DateTime.Now
                    periodFilters = GetPeriodFilter(dateStart, dateEnd)

                ElseIf decStartDate.Value Is Nothing AndAlso decEndDate.Value IsNot Nothing Then
                    dateStart = Date.MinValue
                    dateEnd = ConvertToDateTime(decEndDate.Value)
                    periodFilters = GetPeriodFilter(dateStart, dateEnd)

                End If

                toReturn.FilterQuery = periodFilters
                Return toReturn

            ElseIf rbDate.Checked Then
                dateStart = ConvertToDateTime(decSpecificDate.Value)
                toReturn.FilterQuery = GetDateFilter(dateStart)
                Return toReturn
            End If

            Return Nothing

        End Function

        Public Overrides Function HasFilter() As Boolean

            Return (rbPeriod.Checked AndAlso _
                (decStartDate.Value IsNot Nothing AndAlso Not String.IsNullOrEmpty(decStartDate.Value.ToString)) OrElse _
                (decEndDate.Value IsNot Nothing AndAlso Not String.IsNullOrEmpty(decEndDate.Value.ToString))) OrElse _
                (rbDate.Checked AndAlso _
                 decSpecificDate.Value IsNot Nothing AndAlso _
                 Not String.IsNullOrEmpty(decSpecificDate.Value.ToString))

        End Function

        Public Overrides Function GetFieldNames() As IEnumerable(Of String)

            Return New String() {FieldName}

        End Function

        Public Overrides Function ParseFilter(ByVal objFilter As LuceneFilterQuery) As Boolean

            If TypeOf (objFilter.FilterQuery) Is TermRangeQuery Then
                Dim tRangeQ As TermRangeQuery = DirectCast(objFilter.FilterQuery, TermRangeQuery)
                If tRangeQ.Field = FieldName Then
                    decStartDate.Value = ParseDate(tRangeQ.LowerTerm)
                    decSpecificDate.Value = decStartDate.Value
                    decEndDate.Value = ParseDate(tRangeQ.UpperTerm)
                    rbPeriod.Checked = True
                    rbDate.Checked = False
                    rb_CheckedChanged(rbDate, New EventArgs)
                    Return True
                End If
            ElseIf TypeOf objFilter.FilterQuery Is PrefixQuery Then ' ne pas oublier le cas d'une date unique
                Dim PQ As PrefixQuery = DirectCast(objFilter.FilterQuery, PrefixQuery)
                If PQ.Prefix().Field = FieldName Then
                    decSpecificDate.Value = ParseDate(PQ.Prefix().Text)
                    decStartDate.Value = decSpecificDate.Value
                    rbDate.Checked = True
                    rbPeriod.Checked = False
                    rb_CheckedChanged(rbDate, New EventArgs)
                    Return True
                End If
            End If


            Return False
        End Function

#End Region

#Region "Events handler"

        Private Sub rb_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles rbPeriod.CheckedChanged, rbDate.CheckedChanged
            If rbPeriod.Checked Then
                rowStartDate.Visible = True
                rowEndDate.Visible = True
                rowSpecificDate.Visible = False
                decStartDate.Value = decSpecificDate.Value
            Else
                rowStartDate.Visible = False
                rowEndDate.Visible = False
                rowSpecificDate.Visible = True
                decSpecificDate.Value = decStartDate.Value
            End If
        End Sub

#End Region

#Region "Private Methods"
        ''' <summary>
        '''  ConvertToDateTime DateTimeEditControl Value (DNN >= 5.5 -> Changement 'Value' has InvariantCulture )
        ''' </summary>
        ''' <param name="datePeriod"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function ConvertToDateTime(ByVal datePeriod As Object) As DateTime
            Dim toReturn As DateTime = Null.NullDate
            If NukeHelper.DnnVersion.Major > 5 OrElse (NukeHelper.DnnVersion.Major = 5 AndAlso NukeHelper.DnnVersion.Minor >= 5) Then ' condition corrigée
                toReturn = Convert.ToDateTime(datePeriod, CultureInfo.InvariantCulture)
            Else
                toReturn = Convert.ToDateTime(datePeriod)
            End If
            Return toReturn
        End Function

        ''' <summary>
        ''' Get Period Filter
        ''' </summary>
        ''' <param name="dateStart"></param>
        ''' <param name="dateEnd"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function GetPeriodFilter(ByVal dateStart As DateTime, ByVal dateEnd As DateTime) As TermRangeQuery
            Dim periodStart As String
            Dim periodEnd As String

            ' on rééquilibre les dates pour inclure l'ensemble de la journée
            dateStart = New DateTime(dateStart.Year, dateStart.Month, dateStart.Day, 0, 0, 0)
            dateEnd = New DateTime(dateEnd.Year, dateEnd.Month, dateEnd.Day, 23, 59, 59)

            If UseLucenDateFormat Then
                periodStart = BusinessController.FormatSearchCriteria(DateTools.DateToString(dateStart, DateTools.Resolution.SECOND))
                periodEnd = BusinessController.FormatSearchCriteria(DateTools.DateToString(dateEnd, DateTools.Resolution.SECOND))
            Else
                periodStart = BusinessController.FormatSearchCriteria(dateStart.ToString("yyyyMMdd"))
                periodEnd = BusinessController.FormatSearchCriteria(dateEnd.ToString("yyyyMMdd"))
            End If

            Dim TQ As New TermRangeQuery(FieldName, periodStart, periodEnd, True, True)
            TQ.RewriteMethod = MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE
            Return TQ
        End Function

        ''' <summary>
        ''' Get Date Filter
        ''' </summary>
        ''' <param name="dateStart"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function GetDateFilter(ByVal dateStart As DateTime) As Query
            Dim dayToSearch As String
            ' on va faire une recherche en préfixe car la date de publication est sauvegardée à la seconde prêt. On aurait pu faire une termrangequery
            ' mais on va laisser ça logiquement à la range...
            If UseLucenDateFormat Then
                dayToSearch = BusinessController.FormatSearchCriteria(DateTools.DateToString(dateStart, DateTools.Resolution.DAY))
            Else
                dayToSearch = BusinessController.FormatSearchCriteria(dateStart.ToString("yyyyMMdd"))
            End If
            Dim PQ As New PrefixQuery(New Term(FieldName, dayToSearch))
            PQ.RewriteMethod = PrefixQuery.SCORING_BOOLEAN_QUERY_REWRITE
            Return New PrefixQuery(New Term(FieldName, dayToSearch))
        End Function

        ''' <summary>
        ''' Parse Date (DNN >= 5.5 -> Changement 'Value' has InvariantCulture )
        ''' </summary>
        ''' <param name="dateToParse"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function ParseDate(ByVal dateToParse As String) As String
            Dim toReturn As String = String.Empty
            If NukeHelper.DnnVersion.Major > 5 OrElse (NukeHelper.DnnVersion.Major = 5 AndAlso NukeHelper.DnnVersion.Minor >= 5) Then ' condition corrigée
                toReturn = DateTools.StringToDate(dateToParse).ToString(CultureInfo.InvariantCulture)
            Else
                toReturn = DateTools.StringToDate(dateToParse).ToString()
            End If
            Return toReturn
        End Function
#End Region

    End Class

End Namespace